package com.dance.sharevalidator.config;

import com.dance.sharevalidator.exception.ValidListException;
import com.dance.sharevalidator.vo.ResultVo;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Path;
import javax.validation.ValidationException;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@RestControllerAdvice
public class HandlerException {

    @ExceptionHandler
    public ResultVo<Object> exceptionHandler(MethodArgumentNotValidException exception) {
        Map<String, String> errorMap = exception.getBindingResult()
                .getFieldErrors()
                .stream()
                .collect(Collectors.toMap(FieldError::getField, FieldError::getDefaultMessage));
        return ResultVo.error("参数错误", errorMap);
    }

    @ExceptionHandler
    public ResultVo<Object> exceptionHandler(ConstraintViolationException exception) {
        Map<Path, String> errorMap = exception.getConstraintViolations()
                .stream()
                .collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage));
        return ResultVo.error("参数错误", errorMap);
    }

    @ExceptionHandler
    public ResultVo<Object> exceptionHandler(ValidationException exception) {
        Throwable cause = exception.getCause();
        if (cause instanceof ValidListException) {
            Map<Integer, Map<Path, String>> errorMap = new HashMap<>();
            ValidListException validListException = (ValidListException)cause;
            validListException.getErrors().forEach((i, c) -> {
                Map<Path, String> value = c.stream().collect(Collectors.toMap(ConstraintViolation::getPropertyPath, ConstraintViolation::getMessage));
                errorMap.put(i, value);
            });
            return ResultVo.error("参数错误", errorMap);
        }
        return ResultVo.error("系统异常");
    }

    /**
     * 为了防止前端直接报错, 做统一异常拦截,提示系统错误
     *
     * @param exception 统一异常
     * @return 系统异常
     */
    @ExceptionHandler
    public ResultVo<Object> exceptionHandler(Exception exception) {
        exception.printStackTrace();
        return ResultVo.error("系统异常");
    }
}
